<template>
  <div class="container flow-model-container flow-model-container-editable" ref="container">
    <svg :id="containerID" :style="svgStyle" ref="FlowModel" class="flow-image">
      <g/>
    </svg>
  </div>
</template>

<script>
import FlowModelEditor from '@/components/flow/FlowModelEditor';
import FlowHistoryImageHelper from '@/components/flow/FlowHistoryImageHelper';
import {isEmpty, isNotEmpty} from '@/utils/CommonUtils';

export default {
  name: 'FlowModel',
  extends: FlowModelEditor,
  mounted() {
    this.resolveContainerStyle();
    this.renderFlowModel();
  },
  data() {
    return {
      flowImageHistory: {
        activeNodes: [],
        passedNodes: [],
        flowModel: undefined
      }
    };
  },
  methods: {
    setFlowImageHistory(flowImageHistory) {
      this.flowImageHistory = flowImageHistory;
      this.parseFlowImage();

      this.$nextTick(() => {
        this.renderFlowModel();
      });
    },
    parseFlowImage() {
      let helper = new FlowHistoryImageHelper(this.flowImageHistory, this.flowModel);
      this.flowModel = helper.parse();
      this.$nextTick(() => {
        this.renderFlowModel();
      });
    },
    prepareDraw() {
      let svg = d3.select(`#${this.containerID}`);
      let inner = svg.select("g");
      let graph = new dagreD3.graphlib.Graph();
      graph.setGraph({
        rankdir: "LR",
        marginx: 20,
        marginy: 20
      });
      let zoom = d3.zoom().on("zoom", function () {
        inner.attr("transform", d3.event.transform);
      });
      svg.call(zoom);
      return {
        svg,
        inner,
        render: new dagreD3.render(),
        graph
      };
    },
    drawLines({graph}) {
      let lines = this.flowModel.lines;
      for (let i = 0; i < lines.length; i++) {
        let label = '';
        if (lines[i].formula) {
          label = `<span class="line-formula-text">${lines[i].formula.formulaTitle}</span>`;
        }

        let line = {
          labelType: "html",
          label,
          'class': lines[i].className
        };
        this.resolveLineStyle(line, lines[i]);
        graph.setEdge(lines[i].start, lines[i].end, line);
      }
    },
    resolveLineStyle(line, lineDefinition) {
      if (isEmpty(line) || isEmpty(line.label)) return;
      let label = line.label;
      label = $(label);
      let className = lineDefinition.className;
      label.addClass(className);
      try {
        line.label = label[0].outerHTML;
      } catch (e) {
      }
    },
    resolveNodeStyle(node, nodeDefinition) {
      if (node.id === 'start' || node.id === 'end') {
        let list = [...this.flowImageHistory.activeNodes, ...this.flowImageHistory.passedNodes];
        if (isNotEmpty(list.find(id => id === node.id))) {
          let label = node.node.label;
          label = $(label);
          label.addClass('common-node-passed');
          node.node.label = label[0].outerHTML;
        }
        return;
      }
      if (isEmpty(nodeDefinition) || isEmpty(nodeDefinition.className)) {
        return;
      }

      let className = nodeDefinition.className;
      let label = node.node.label;
      label = $(label);
      label.addClass(className);
      node.node.label = label[0].outerHTML;
    },
    elementClick(e) {
      let {target} = e;
      this.$emit('flowElementClick', target);
    },
    bindActions() {
      let labels = $(`#${this.containerID}`).find('.label');
      labels.unbind('click', this.elementClick);
      labels.off('click');
      labels.on('click', this.elementClick);
    },
  }
};
</script>

<style scoped>
.container {
  background: #e0e0e0;
}

.container {
  background: #e0e0e0;
  position: relative;
}

.flow-image {
  min-width: 100%;
  min-height: 500px;
  height: 100%;
}

.flow-model-container-editable {
  height: 100%;
  overflow: auto;
}
</style>
